#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "reed_sol-2.h"
#include "jerasure-2.h"
#include "galois-2.h"

using namespace std;

int main( int argc, char** argv )
{
	JER_Matrix *jm;
	JER_Slices *data;

	unsigned char *buf, *orig;

	int i, j;
	uint64_t l;
	FILE* fp;
	vector <int> erasures;
	int m = atoi( argv[1] );
	int k = atoi( argv[2] );
	int w = atoi( argv[3] );

	jm = reed_sol_vandermonde_coding_matrix( k, m, w );
	srand48(0);
	data = new JER_Slices();
	data->K = k;
	data->M = m;
	data->W = w;
	data->PS = sizeof(uint64_t);
	data->size = data->PS;

	data->ptrs.resize(k+m);
	buf = (unsigned char *) malloc(sizeof(uint64_t)*(k+m));
	fp = fopen( argv[4], "r" );
	fread( buf, sizeof(uint64_t), k+m, fp );
	for (i = 0; i < k; i++) {
	/*	l = lrand48();
		l <<= 8*4;
		l += lrand48();
		memcpy(buf+i*sizeof(uint64_t), &l, sizeof(uint64_t));*/
		data->ptrs[i] = buf + i*sizeof(uint64_t);
		fwrite( data->ptrs[i], 1, sizeof(uint64_t), stdout );
		fprintf( stdout, "\n" );
	}
	for (; i < k+m; i++) {
		data->ptrs[i] = buf + (i)*sizeof(uint64_t);
	}

	orig = (unsigned char* ) malloc( sizeof(uint64_t)*(k+m) );
	JER_Matrix_Encode( data, jm );
	
	for( i = 0; i < k + m; i++ )
	{
		fwrite( data->ptrs[i], 1, sizeof(uint64_t), stdout );
		fprintf( stdout, "\n" );
	}
/*
	memcpy( orig, buf, sizeof(uint64_t)*(k+m) );
	
	jm->Print();
*/
	data->failures.resize( k + m, 0 );
	for( i = 0; i < m; i++ )
	{
		j = lrand48() % ( k + m );
		if( data->failures[j] != 0 )
			i--;
		data->failures[j] = 1;
		memset( data->ptrs[j], 0, data->size );
	}

	fprintf( stdout, "--------------\n" );
	for( i = 0; i < k + m; i++ )
	{
		if( data->failures[i] == 1 )
			erasures.push_back(i);
		fwrite( data->ptrs[i], 1, sizeof(uint64_t), stdout );
		fprintf( stdout, "\n" );
	}
	fprintf( stdout, "--------------\n" );
	if( JER_Matrix_Decode( data, jm, 0, erasures ) < 0 )
		fprintf( stderr, "Failed to decode correctly\n" );
	for( i = 0; i < k + m; i++ )
	{
		fwrite( data->ptrs[i], 1, sizeof(uint64_t), stdout );
		fprintf( stdout, "\n" );
	}
	fprintf( stdout, "--------------\n" );
/*
	jm->Print();

	if( memcmp( orig, buf, sizeof(uint64_t)*(k+m) ) == 0 )
		fprintf( stdout, "Both memory blocks are the same.\n" );
*/
	return 0;
}
